package main

import (
	"context"
	"flag"
	"fmt"
	"log"
	"net/http"
	"strconv"
	"sync"
	"time"

	"youbei/static"
	"youbei/utils/config"
	"youbei/utils/jobs"

	YouBeiStorage "youbei/YouBeiStorage/controllers"
	YBClientControllers "youbei/client/controllers"
	YouBeicontrollers "youbei/server/controllers"

	"youbei/dao"

	"github.com/beego/beego/toolbox"
	"github.com/gin-gonic/gin"
)

var devon = false

var (
	wg      sync.WaitGroup
	servers = make(map[string]*http.Server) // a map to store the servers
)

func main() {
	dbdir := flag.String("dbdir", "", "存储路径")

	fmt.Println(*dbdir)

	dao.Init(*dbdir)

	fmt.Println(dao.DBdir)
	config.Init(dao.DBdir)

	// 1. 加载配置文件
	conf, err := config.LoadConfigFromFile()
	if err != nil {
		log.Fatalf("Error loading config file: %v", err)
	}

	// 2. 使用配置文件的值初始化命令行参数
	serverEnabled := flag.Bool("server.enabled", conf.ConfServer.Enabled, "启用服务器")
	serverPort := flag.Int("server.port", conf.ConfServer.Port, "服务器端口")
	clientEnabled := flag.Bool("client.enabled", conf.ConfClient.Enabled, "启用客户端")
	clientPort := flag.Int("client.port", conf.ConfClient.Port, "客户端端口")
	yserverEnabled := flag.Bool("yserver.enabled", conf.ConfYserver.Enabled, "启用Y服务器")
	yserverPort := flag.Int("yserver.port", conf.ConfYserver.Port, "YServer端口")
	yserverUser := flag.String("yserver.user", conf.ConfYserver.User, "登录用户")
	yserverPassword := flag.String("yserver.password", conf.ConfYserver.Password, "登录密码")
	yserverSavepath := flag.String("yserver.savepath", conf.ConfYserver.Savepath, "存储路径")

	// 3. 解析命令行参数
	flag.Parse()

	// 4. 更新配置文件的值
	conf.ConfServer.Enabled = *serverEnabled
	conf.ConfServer.Port = *serverPort
	conf.ConfClient.Enabled = *clientEnabled
	conf.ConfClient.Port = *clientPort
	conf.ConfYserver.Enabled = *yserverEnabled
	conf.ConfYserver.Port = *yserverPort
	conf.ConfYserver.User = *yserverUser
	conf.ConfYserver.Password = *yserverPassword
	conf.ConfYserver.Savepath = *yserverSavepath

	// 5. 将配置保存回文件
	err = config.SaveConfigToFile(conf)
	if err != nil {
		log.Fatalf("Error saving config file: %v", err)
	}

	// 6. 根据配置启动服务
	if conf.ConfServer.Enabled {
		// Module 1: management platform
		wg.Add(1)
		go startServerModule(strconv.Itoa(conf.ConfServer.Port))
	}

	if conf.ConfClient.Enabled {
		// Module 2: task execution module
		wg.Add(1)
		go startClientModule(strconv.Itoa(conf.ConfClient.Port))
	}

	if conf.ConfYserver.Enabled {
		// Module 3: data storage reception interface module
		if conf.ConfYserver.Password != "" && conf.ConfYserver.User != "" && conf.ConfYserver.Savepath != "" {
			wg.Add(1)
			go startYserverModule(strconv.Itoa(conf.ConfYserver.Port))
		}
	}

	wg.Wait()
}

func startServerModule(port string) {
	defer wg.Done()

	//============
	go func() {
		log := dao.Log{}
		log.Status = 2
		log.Msg = "程序异常退出，备份失败"
		if _, err := dao.Localdb().Where("status=1").Cols("status", "msg").Update(&log); err != nil {
			panic(err)
		}
		log.Status = -1
		log.RecoveryErrMsg = "程序异常退出，数据还原失败"
		if _, err := dao.Localdb().Where("status=3").Cols("status", "recoveryErrMsg").Update(&log); err != nil {
			panic(err)
		}

		ts, err := dao.All()
		if err != nil {
			panic(err)
		}
		if len(ts) > 0 {
			for _, ob := range ts {
				toolbox.AddTask(ob.ID, toolbox.NewTask(ob.ID, ob.Crontab, jobs.Jobs(ob.ID)))
			}
		}
		toolbox.StartTask()
	}()

	r := gin.Default()
	r.Use(YouBeicontrollers.Cors())

	devon = false
	if !devon {
		r.StaticFS("/ui", http.FS(static.Static))
		r.StaticFS("/static", http.FS(static.Static))
	}

	r.GET("/", func(c *gin.Context) {
		c.Redirect(http.StatusMovedPermanently, "/ui")
	})

	r.GET("/downloadfile/:id", YouBeicontrollers.DownloadFile)
	r.GET("/login/:name/:password", YouBeicontrollers.Userlogin)

	// r.POST("/upload/packet/:id/:offset", YouBeicontrollers.Uploadpacket)
	// r.POST("/upload/done/:id", YouBeicontrollers.UploadpacketDone)
	// r.POST("/upload/file/:id", YouBeicontrollers.UploadFile)

	//r.GET("/service/upload", YouBeicontrollers.Yserverlist)
	// server.GET("/start_yserver", func(c *gin.Context) {
	// 	go startYserverModule()
	// 	c.String(200, "Started yserver module.")
	// })
	r.PUT("/service/upload/:id", func(c *gin.Context) {
		ob := new(dao.Yserver)
		if err := c.Bind(ob); err != nil {
			res := gin.H{
				"success": 500,
				"msg":     "解析失败",
				"result":  err.Error(),
			}
			c.AbortWithStatusJSON(500, res)
			return
		}

		if err := ob.EnableYserver(); err != nil {
			res := gin.H{
				"success": 500,
				"msg":     "服务启动失败",
				"result":  err.Error(),
			}
			c.AbortWithStatusJSON(500, res)
			return
		}
		if ob.Enable {
			go startYserverModule(strconv.Itoa(ob.Port))
		} else {
			stopModule("yserver")
		}

		res := gin.H{
			"success": 200,
			"msg":     "服务修改成功",
			"result":  "",
		}
		c.AbortWithStatusJSON(200, res)
		return
	})
	//r.DELETE("/service/upload/:id", YouBeicontrollers.DisableServer)

	api := r.Group("/api")
	api.Use(YouBeicontrollers.Prepare())
	{
		api.GET("/tasks", YouBeicontrollers.GetTasks)
		api.GET("/task/:id", YouBeicontrollers.GetTask)
		api.POST("/task", YouBeicontrollers.AddTask)
		api.PUT("/task/:id", YouBeicontrollers.UpdateTask)
		api.DELETE("/task/:id", YouBeicontrollers.DeleteTask)

		api.GET("/logs", YouBeicontrollers.Loglist)
		api.GET("/log/:id", YouBeicontrollers.ShowLog)

		api.GET("/rlogs", YouBeicontrollers.Rloglist)
		api.GET("/rlog/:id", YouBeicontrollers.ShowrLog)

		api.GET("/ftps", YouBeicontrollers.Ftplist)
		api.GET("/ftp/:id", YouBeicontrollers.Ftpfind)
		api.POST("/ftp", YouBeicontrollers.Ftpadd)
		api.DELETE("/ftp/:id", YouBeicontrollers.Ftpdelete)
		api.PUT("/ftp/:id", YouBeicontrollers.Ftpupdate)

		api.PUT("/runjob/:id", YouBeicontrollers.RunJob)

		api.GET("/dirlist/:hostid", YouBeicontrollers.Proxy)

		api.GET("/hosts", YouBeicontrollers.HostsGet)
		api.GET("/host/:id", YouBeicontrollers.HostGet)
		api.PUT("/host/:id", YouBeicontrollers.HostUpdate)
		api.DELETE("/host/:id", YouBeicontrollers.HostDelete)
		api.POST("/host", YouBeicontrollers.HostAdd)

		api.GET("/users", YouBeicontrollers.UserList)
		api.GET("/user/:id", YouBeicontrollers.GetUser)
		api.POST("/user", YouBeicontrollers.AddUser)
		api.PUT("/user/:id", YouBeicontrollers.EditUser)
		api.DELETE("/user/:id", YouBeicontrollers.DeleteUser)

		api.PUT("/pchange/:id", YouBeicontrollers.Userchangepwd)

		api.POST("/mailserver", YouBeicontrollers.MailTest)
		api.PUT("/mailserver", YouBeicontrollers.MailServerUpdate)
		api.GET("/mailserver", YouBeicontrollers.GetMail)

		api.PUT("/connecthost/:id", YouBeicontrollers.ConnectHost)

		api.GET("/getdbinfo/:hostid", YouBeicontrollers.Proxy)
		api.GET("/getcmds/:hostid", YouBeicontrollers.Proxy)
		api.GET("/getcmd/:hostid", YouBeicontrollers.Proxy)
		api.PUT("/getcmd/:hostid", YouBeicontrollers.Proxy)

		api.GET("/sysinfo", YouBeicontrollers.Sysinfo)
		api.GET("/dashboardinfo", YouBeicontrollers.DashBoardInfo)
		api.GET("/getlocal/:hostid", YouBeicontrollers.Proxy)
		api.PUT("/sqlrecovery/:id", YouBeicontrollers.SqlRecovery)
		api.GET("/crontablist", YouBeicontrollers.GetCrontabList)
		api.POST("/crontab", YouBeicontrollers.AddCrontab)
		api.DELETE("/crontab/:id", YouBeicontrollers.DeleteCrontab)
		api.GET("/crontab/:id", YouBeicontrollers.GetCrontab)
		api.PUT("/crontab/:id", YouBeicontrollers.UpdateCrontab)

	}

	client := r.Group("/client")
	client.Use(YouBeicontrollers.ClientPrepare())
	{
		client.POST("/updatelog", YouBeicontrollers.UpdateLog)
		client.POST("/updaterlog", YouBeicontrollers.UpdateRLog)
		client.POST("/addyslog", YouBeicontrollers.AddYSLog)
		client.POST("/addyspacketlog", YouBeicontrollers.AddYSpacketLog)
		client.POST("/updateYsPacketLog", YouBeicontrollers.UpdateYSpacketLog)
	}

	s := &http.Server{
		Addr:    ":" + port,
		Handler: r,
	}

	servers["server"] = s
	s.ListenAndServe()
}

func startClientModule(port string) {
	defer wg.Done()
	r := gin.Default()
	r.POST("/client/stepone", YBClientControllers.ClientApiStepOne)
	r.POST("/client/steptwo", YBClientControllers.ClientApiStepTwo)
	api := r.Group("/api")
	api.Use(YBClientControllers.Prepare())
	{
		api.GET("/getcmds/:hostid", YBClientControllers.CmdList)
		api.GET("/getcmd/:hostid", YBClientControllers.GetCmd)
		api.PUT("/getcmd/:hostid", YBClientControllers.UpdateCmd)
		api.GET("/dirlist/:hostid", YBClientControllers.DirList)
		api.GET("/getlocal/:hostid", YBClientControllers.GetLocal)
		api.GET("/getdbinfo/:hostid", YBClientControllers.DBGet)
		api.POST("/runjob", YBClientControllers.RunJob)
	}

	s := &http.Server{
		Addr:    ":" + port,
		Handler: r,
	}

	servers["client"] = s
	s.ListenAndServe()
}

func startYserverModule(port string) {
	defer wg.Done()
	r := gin.Default()
	r.POST("/yserver/stepone", YouBeiStorage.ClientApiStepOne)
	r.POST("/yserver/steptwo", YouBeiStorage.ClientApiStepTwo)
	r.POST("/upload/packet/:id/:offset", YouBeiStorage.Uploadpacket)
	r.POST("/upload/done/:id", YouBeiStorage.UploadpacketDone)
	r.POST("/upload/file/:id", YouBeiStorage.UploadFile)
	api := r.Group("/api")
	api.Use()
	{
		api.GET("/uploadlogs", YouBeiStorage.Uploadlogs)
		api.GET("/uploadlog/:id", YouBeiStorage.GetYserverLog)
	}
	r.GET("/data", func(c *gin.Context) {
		c.String(200, "This is data storage reception interface module.")
	})

	s := &http.Server{
		Addr:    ":" + port,
		Handler: r,
	}

	servers["yserver"] = s
	s.ListenAndServe()
}

func stopModule(name string) {
	server, exists := servers[name]
	if exists {
		ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
		defer cancel()
		if err := server.Shutdown(ctx); err != nil {
			fmt.Printf("Server Shutdown Failed:%+v", err)
		}
		delete(servers, name)
	}
}

// func main() {

// 	r.Run()
// }
